package cn.szsys.integration.helper.business.impl;

import cn.szsys.integration.billrule.BillingMapperUtils;
import cn.szsys.integration.billrule.annoation.BillRule;
import cn.szsys.integration.billrule.entity.BillingInfo;
import cn.szsys.integration.constants.BillRuleRecordTypeEnum;
import cn.szsys.integration.constants.ZsxyInvestmentMapperedEnum;
import cn.szsys.integration.dto.InvestmentDTO;
import cn.szsys.integration.dto.ZsxyInvestmentResDTO;
import cn.szsys.integration.dto.ZsxyRelatedResDTO;
import cn.szsys.integration.ex.BusinessException;
import cn.szsys.integration.ex.enums.ExceptionEnum;
import cn.szsys.integration.helper.BusinessBeanNameConstant;
import cn.szsys.integration.helper.business.AbstractInvestmentHandlerChain;
import cn.szsys.integration.util.OkHttpUtil;
import cn.szsys.integration.util.R;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 中胜信用(c1.0)
 *
 * @author Ryan
 * @since 2025-05-17
 **/
@Component(BusinessBeanNameConstant.Investment.ZSXY_INVESTMENT_HANDLER_CHAIN)
@Slf4j
public class ZsxyInvestmentHandlerChain extends AbstractInvestmentHandlerChain {

    /**
     * 企业基础信息produceCode
     */
    private static final String BASE_INFO_PRODUCT_CODE = "E_002_0081";
    /**
     * 企业关联信息produceCode
     */
    private static final String RELATED_PRODUCT_CODE = "P_002_1031";


    @Value("${investment.zhongsheng.url}")
    private String url;
    @Value("${investment.zhongsheng.app-code}")
    private String appCode;

    /**
     * 转换对应结果并设置计费信息
     * 由于此类需要执行多个不同请求,此方法不做转换
     *
     * @param obj           obj
     * @param consumingTime consumingTime
     * @return {@link R}
     * @author Ryan
     */
    @Override
    public R<?> convertResultAndBilling(JSONObject obj, long consumingTime) {
        return null;
    }

    /**
     * 执行业务处理
     *
     * @param dto          参数
     * @param reqStartTime reqStartTime
     * @return {@link R}
     * @author Ryan
     */
    @Override
    public R<?> doHandle(InvestmentDTO dto, long reqStartTime) {
        //企业关联信息
        if (Objects.equals(dto.getRouter(), InvestmentDTO.RouterEnum.RELATED)) {
            ZsxyInvestmentHandlerChain thisChain = (ZsxyInvestmentHandlerChain) AopContext.currentProxy();
            return thisChain.reqRelated(dto.getIdCardMd5(), reqStartTime);
        }

        //企业关联信息
        if (Objects.equals(dto.getRouter(), InvestmentDTO.RouterEnum.BASE_INFO)) {
            ZsxyInvestmentHandlerChain thisChain = (ZsxyInvestmentHandlerChain) AopContext.currentProxy();
            return thisChain.reqBaseInfo(dto.getKey(), reqStartTime);
        }

        return null;
    }

    /**
     * 查询企业关联信息
     *
     * @param idCardMd5    idCardMd5
     * @param reqStartTime reqStartTime
     * @return {@link R<?>}
     * @author Ryan
     */
    @BillRule(upstream = "zhongshengxinyong", billRuleRecordType = BillRuleRecordTypeEnum.DAY, product = "人企投资核查C1.0")
    public R<?> reqRelated(String idCardMd5, long reqStartTime) {
        Map<String, String> headerMap = buildHeaderMap(RELATED_PRODUCT_CODE);
        JSONObject req = new JSONObject();
        req.put("idCard_md5", idCardMd5);
        log.info("请求ZSXY查询企业关联信息[请求], header :{}, body :{}", headerMap, req);

        long startTime = System.currentTimeMillis();
        OkHttpUtil.OkhttpResponse response = OkHttpUtil.builder()
                .url(url)
                .addHeaders(headerMap)
                .post(req.toString())
                .sync();
        long endTime = System.currentTimeMillis();
        log.info("请求ZSXY查询企业关联信息[响应], response: {}, 请求耗时: {}ms", response.getData(), (endTime - startTime));
        if (response.getSuccess()) {
            String data = response.getData();
            ZsxyRelatedResDTO zsxyRelatedRes = JSON.parseObject(data, ZsxyRelatedResDTO.class);
            return relatedResultConvertAndBilled(zsxyRelatedRes, reqStartTime - startTime);
        }
        throw new BusinessException(ExceptionEnum.OP_FAIL, "请求出错!");
    }

    /**
     * 查询企业基本信息
     *
     * @param key          key
     * @param reqStartTime reqStartTime
     * @return {@link R<?>}
     * @author Ryan
     */
    @BillRule(upstream = "zhongshengxinyong", billRuleRecordType = BillRuleRecordTypeEnum.DAY, product = "企业基本信息核查D1.0")
    public R<?> reqBaseInfo(String key, long reqStartTime) {
        Map<String, String> headerMap = buildHeaderMap(BASE_INFO_PRODUCT_CODE);
        JSONObject req = new JSONObject();
        req.put("key", key);
        log.info("请求ZSXY查询企业基本信息[请求], header :{}, body :{}", headerMap, req);

        long startTime = System.currentTimeMillis();
        OkHttpUtil.OkhttpResponse response = OkHttpUtil.builder()
                .url(url)
                .addHeaders(headerMap)
                .post(req.toString())
                .sync();
        long endTime = System.currentTimeMillis();
        log.info("请求ZSXY查询企业基本信息[响应], response: {}, 请求耗时: {}ms", response.getData(), (endTime - startTime));
        if (response.getSuccess()) {
            String data = response.getData();
            ZsxyInvestmentResDTO zsxyRelatedRes = JSON.parseObject(data, ZsxyInvestmentResDTO.class);
            return baseResultConvertAndBilled(zsxyRelatedRes, reqStartTime - startTime);
        }
        throw new BusinessException(ExceptionEnum.OP_FAIL, "请求出错!");
    }


    /**
     * 构建header
     *
     * @param productCode productCode
     * @return {@link Map< String, String>}
     * @author Ryan
     */
    private Map<String, String> buildHeaderMap(String productCode) {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("AppCode", appCode);
        headerMap.put("pcode", productCode);
        return headerMap;
    }

    /**
     * 结果转换(企业关联信息请求结果)
     *
     * @param dto           dto
     * @param consumingTime consumingTime
     * @return {@link R<?>}
     * @author Ryan
     */
    private R<?> relatedResultConvertAndBilled(ZsxyRelatedResDTO dto, long consumingTime) {
        String resultCode;
        if (dto.isSuccess()) {
            resultCode = dto.getCharge() ? "1" : "0";
        }else{
            resultCode= "0";
        }
        ZsxyInvestmentMapperedEnum byUpstreamCode = ZsxyInvestmentMapperedEnum.getByUpstreamCode(resultCode);
        BillingInfo billingInfo = BillingInfo.build(byUpstreamCode.getDownstreamCode(), resultCode, consumingTime);
        BillingMapperUtils.set(billingInfo);

        return R.success(dto.transform());
    }


    /**
     * 结果转换(企业接触信息请求结果)
     *
     * @param dto           dto
     * @param consumingTime consumingTime
     * @return {@link R<?>}
     * @author Ryan
     */
    private R<?> baseResultConvertAndBilled(ZsxyInvestmentResDTO dto, long consumingTime) {
        String resultCode;
        if (dto.isSuccess()) {
            resultCode = dto.getCharge() ? "1" : "0";
        }else{
            resultCode= "0";
        }
        ZsxyInvestmentMapperedEnum byUpstreamCode = ZsxyInvestmentMapperedEnum.getByUpstreamCode(resultCode);
        BillingInfo billingInfo = BillingInfo.build(byUpstreamCode.getDownstreamCode(), resultCode, consumingTime);
        BillingMapperUtils.set(billingInfo);
        return R.success(dto.returnData());
    }
}
